import java.util.HashSet;
import java.util.Set;

/**
 * CalculationSystemV03的测试类
 * 测试系统的主要功能：习题生成、无重复特性、加减法比例控制和结果限制等
 */
public class CalculationSystemV03Test {

    public static void main(String[] args) {
        System.out.println("开始测试加减法口算练习系统 V0.3...");
        System.out.println("========================================");
        
        // 运行所有测试
        boolean allTestsPassed = true;
        
        allTestsPassed &= testExerciseGeneration();
        allTestsPassed &= testUniqueExercises();
        allTestsPassed &= testAdditionSubtractionRatio();
        allTestsPassed &= testResultConstraints();
        allTestsPassed &= testExerciseMethods();
        
        System.out.println("========================================");
        if (allTestsPassed) {
            System.out.println("所有测试通过！系统功能正常。");
        } else {
            System.out.println("部分测试失败，请检查系统实现。");
        }
    }
    
    /**
     * 测试习题生成功能
     */
    private static boolean testExerciseGeneration() {
        System.out.println("\n测试1: 习题生成功能");
        System.out.println("----------------------------------------");
        
        ExerciseGenerator generator = new ExerciseGenerator();
        int testCount = 10; // 测试生成10道题
        Exercise[] exercises = generator.generateUniqueExercises(testCount, 0.5);
        
        boolean testPassed = exercises.length == testCount;
        System.out.println("- 生成指定数量的习题: " + (testPassed ? "通过" : "失败"));
        
        // 显示部分生成的习题
        System.out.println("- 生成的部分习题示例:");
        for (int i = 0; i < Math.min(3, exercises.length); i++) {
            System.out.println("  " + exercises[i]);
        }
        
        return testPassed;
    }
    
    /**
     * 测试无重复习题功能
     */
    private static boolean testUniqueExercises() {
        System.out.println("\n测试2: 无重复习题功能");
        System.out.println("----------------------------------------");
        
        ExerciseGenerator generator = new ExerciseGenerator();
        int testCount = 50; // 生成较多题以增加重复可能性
        Exercise[] exercises = generator.generateUniqueExercises(testCount, 0.5);
        
        // 使用HashSet检查唯一性
        Set<String> uniqueKeys = new HashSet<>();
        for (Exercise exercise : exercises) {
            uniqueKeys.add(exercise.getUniqueKey());
        }
        
        boolean testPassed = uniqueKeys.size() == exercises.length;
        System.out.println("- 确保无重复习题: " + (testPassed ? "通过" : "失败"));
        System.out.println("  实际生成唯一习题数: " + uniqueKeys.size() + ", 预期: " + exercises.length);
        
        // 测试加法交换律是否视为相同算式
        Exercise exercise1 = new Exercise(3, 5, '+');
        Exercise exercise2 = new Exercise(5, 3, '+');
        boolean commutativeProperty = exercise1.getUniqueKey().equals(exercise2.getUniqueKey());
        System.out.println("- 测试加法交换律(3+5和5+3应视为相同): " + (commutativeProperty ? "通过" : "失败"));
        
        return testPassed && commutativeProperty;
    }
    
    /**
     * 测试加减法比例控制功能
     */
    private static boolean testAdditionSubtractionRatio() {
        System.out.println("\n测试3: 加减法比例控制功能");
        System.out.println("----------------------------------------");
        
        ExerciseGenerator generator = new ExerciseGenerator();
        int testCount = 100; // 使用较大样本提高准确性
        double targetRatio = 0.6; // 目标加法比例60%
        Exercise[] exercises = generator.generateUniqueExercises(testCount, targetRatio);
        
        // 统计加法题数量
        int additionCount = 0;
        for (Exercise exercise : exercises) {
            if (exercise.getOperator() == '+') {
                additionCount++;
            }
        }
        
        double actualRatio = (double) additionCount / testCount;
        double tolerance = 0.1; // 允许10%的误差
        boolean testPassed = Math.abs(actualRatio - targetRatio) <= tolerance;
        
        System.out.printf("- 测试加减法比例控制: %s\n", testPassed ? "通过" : "失败");
        System.out.printf("  目标加法比例: %.1f%%, 实际加法比例: %.1f%%\n", 
                targetRatio * 100, actualRatio * 100);
        System.out.printf("  加法题数量: %d, 减法题数量: %d\n", 
                additionCount, testCount - additionCount);
        
        return testPassed;
    }
    
    /**
     * 测试计算结果限制功能
     */
    private static boolean testResultConstraints() {
        System.out.println("\n测试4: 计算结果限制功能");
        System.out.println("----------------------------------------");
        
        ExerciseGenerator generator = new ExerciseGenerator();
        int testCount = 50; // 测试50道题
        Exercise[] exercises = generator.generateUniqueExercises(testCount, 0.5);
        
        boolean allConstraintsPassed = true;
        int additionOverflow = 0;
        int subtractionNegative = 0;
        int invalidNumbers = 0;
        
        for (Exercise exercise : exercises) {
            int a = exercise.getFirstNumber();
            int b = exercise.getSecondNumber();
            char op = exercise.getOperator();
            int result = exercise.getAnswer();
            
            // 检查数字范围是否在100以内
            if (a >= 100 || b >= 100) {
                invalidNumbers++;
                allConstraintsPassed = false;
            }
            
            // 检查加法结果是否小于100
            if (op == '+' && result >= 100) {
                additionOverflow++;
                allConstraintsPassed = false;
            }
            
            // 检查减法结果是否非负
            if (op == '-' && result < 0) {
                subtractionNegative++;
                allConstraintsPassed = false;
            }
        }
        
        System.out.println("- 测试结果限制: " + (allConstraintsPassed ? "通过" : "失败"));
        System.out.println("  加法溢出(>=100)的题目数: " + additionOverflow);
        System.out.println("  减法结果为负数的题目数: " + subtractionNegative);
        System.out.println("  操作数超出范围(>=100)的题目数: " + invalidNumbers);
        
        return allConstraintsPassed;
    }
    
    /**
     * 测试习题类的方法功能
     */
    private static boolean testExerciseMethods() {
        System.out.println("\n测试5: 习题类方法测试");
        System.out.println("----------------------------------------");
        
        // 创建测试用习题
        Exercise addExercise = new Exercise(7, 8, '+');
        Exercise subExercise = new Exercise(15, 6, '-');
        
        boolean testPassed = true;
        
        // 测试答案计算
        if (addExercise.getAnswer() != 15) {
            System.out.println("- 加法答案计算错误: 7+8 应该等于 15，但得到 " + addExercise.getAnswer());
            testPassed = false;
        }
        
        if (subExercise.getAnswer() != 9) {
            System.out.println("- 减法答案计算错误: 15-6 应该等于 9，但得到 " + subExercise.getAnswer());
            testPassed = false;
        }
        
        // 测试字符串输出方法
        String addToString = addExercise.toString();
        if (!addToString.contains("7 + 8 = 15")) {
            System.out.println("- toString()方法输出格式错误: " + addToString);
            testPassed = false;
        }
        
        String addToQuestionString = addExercise.toQuestionString();
        if (!addToQuestionString.contains("7 + 8 = ")) {
            System.out.println("- toQuestionString()方法输出格式错误: " + addToQuestionString);
            testPassed = false;
        }
        
        // 测试唯一性键生成
        Exercise addExerciseSwapped = new Exercise(8, 7, '+');
        if (!addExercise.getUniqueKey().equals(addExerciseSwapped.getUniqueKey())) {
            System.out.println("- getUniqueKey()方法错误: 7+8 和 8+7 应生成相同的键");
            testPassed = false;
        }
        
        if (testPassed) {
            System.out.println("- 所有习题方法测试通过");
        }
        
        return testPassed;
    }
}